# 厦门大学计算机专业 | 前华为工程师
# 专注《零基础学编程系列》  http: // lblbc.cn / blog
# 包含：Java | 安卓 | 前端 | Flutter | iOS | 小程序 | 鸿蒙
# 公众号：蓝不蓝编程
import pygame
import sys
import traceback
import my_plane
import enemy
import bullet

from pygame.locals import *

pygame.init()
pygame.mixer.init()

bg_size = width, height = 480, 700
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption("飞机大战 - 蓝不蓝编程")

background = pygame.image.load("images/background.png").convert()

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

pygame.mixer.music.load("audio/bg.ogg")
pygame.mixer.music.set_volume(0.2)
bullet_sound = pygame.mixer.Sound("audio/bullet.wav")
bullet_sound.set_volume(0.2)
enemy1_down_sound = pygame.mixer.Sound("audio/enemy_plane_down.wav")
enemy1_down_sound.set_volume(0.2)
me_down_sound = pygame.mixer.Sound("audio/my_plane_down.wav")
me_down_sound.set_volume(0.2)


def add_enemy_planes(group1, group2, num):
    for i in range(num):
        e1 = enemy.EnemyPlane(bg_size)
        group1.add(e1)
        group2.add(e1)


def main():
    pygame.mixer.music.play(-1)

    # 生成我方战机
    me = my_plane.MyPlane(bg_size)

    # 生成敌方战机
    enemies = pygame.sprite.Group()
    enemy_planes = pygame.sprite.Group()
    add_enemy_planes(enemy_planes, enemies, 15)

    # 生成子弹
    bullets = []
    bullet_index = 0
    bullet_num = 4
    for i in range(bullet_num):
        bullets.append(bullet.Bullet(me.rect.midtop))

    clock = pygame.time.Clock()

    # 中弹爆炸图序号
    enemy_plane_down_index = 0
    my_plane_down_index = 0

    # 得分
    score = 0
    score_font = pygame.font.SysFont("arial", 36)

    # 标志是否暂停游戏
    paused = False
    pause_nor_image = pygame.image.load("images/pause_nor.png").convert_alpha()
    pause_pressed_image = pygame.image.load("images/pause_pressed.png").convert_alpha()
    resume_nor_image = pygame.image.load("images/resume_nor.png").convert_alpha()
    resume_pressed_image = pygame.image.load("images/resume_pressed.png").convert_alpha()
    paused_rect = pause_nor_image.get_rect()
    paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10
    paused_image = pause_nor_image

    # 生命数量
    life_num = 1

    # 游戏结束画面
    gameover_font = pygame.font.SysFont("arial", 48)
    again_image = pygame.image.load("images/play_again.png").convert_alpha()
    again_rect = again_image.get_rect()
    gameover_image = pygame.image.load("images/quit.png").convert_alpha()
    gameover_rect = gameover_image.get_rect()

    # 用于切换图片
    switch_image = True

    # 用于延迟
    delay = 100

    running = True

    while running:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            elif event.type == MOUSEBUTTONDOWN:
                if event.button == 1 and paused_rect.collidepoint(event.pos):
                    paused = not paused
                    if paused:
                        pygame.mixer.music.pause()
                        pygame.mixer.pause()
                    else:
                        pygame.mixer.music.unpause()
                        pygame.mixer.unpause()

            elif event.type == MOUSEMOTION:
                if paused_rect.collidepoint(event.pos):
                    if paused:
                        paused_image = resume_pressed_image
                    else:
                        paused_image = pause_pressed_image
                else:
                    if paused:
                        paused_image = resume_nor_image
                    else:
                        paused_image = pause_nor_image

        screen.blit(background, (0, 0))

        if life_num and not paused:
            # 检测用户的键盘操作
            key_pressed = pygame.key.get_pressed()

            if key_pressed[K_w] or key_pressed[K_UP]:
                me.moveUp()
            if key_pressed[K_s] or key_pressed[K_DOWN]:
                me.moveDown()
            if key_pressed[K_a] or key_pressed[K_LEFT]:
                me.moveLeft()
            if key_pressed[K_d] or key_pressed[K_RIGHT]:
                me.moveRight()

            # 发射子弹
            if not (delay % 10):
                bullet_sound.play()
                bullets = bullets
                bullets[bullet_index].reset(me.rect.midtop)
                bullet_index = (bullet_index + 1) % bullet_num

            # 检测子弹是否击中敌机
            for b in bullets:
                if b.active:
                    b.move()
                    screen.blit(b.image, b.rect)
                    enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
                    if enemy_hit:
                        b.active = False
                        for e in enemy_hit:
                            e.active = False

            # 绘制敌机：
            for each in enemy_planes:
                if each.active:
                    each.move()
                    screen.blit(each.image, each.rect)
                else:
                    # 毁灭
                    if not (delay % 3):
                        if enemy_plane_down_index == 0:
                            enemy1_down_sound.play()
                        screen.blit(each.destroy_images[enemy_plane_down_index], each.rect)
                        enemy_plane_down_index = (enemy_plane_down_index + 1) % 4
                        if enemy_plane_down_index == 0:
                            score += 1
                            each.reset()

            # 检测我方战机是否被撞
            enemies_down = pygame.sprite.spritecollide(me, enemies, False, pygame.sprite.collide_mask)
            if enemies_down and not me.invincible:
                me.active = False
                for e in enemies_down:
                    e.active = False

            # 绘制我方战机
            if me.active:
                if switch_image:
                    screen.blit(me.image1, me.rect)
                else:
                    screen.blit(me.image2, me.rect)
            else:
                # 毁灭
                if not (delay % 3):
                    if my_plane_down_index == 0:
                        me_down_sound.play()
                    screen.blit(me.destroy_images[my_plane_down_index], me.rect)
                    my_plane_down_index = (my_plane_down_index + 1) % 4
                    if my_plane_down_index == 0:
                        life_num -= 1
                        me.reset()

            # 绘制得分
            score_text = score_font.render("Score: %s" % str(score), True, WHITE)
            screen.blit(score_text, (10, 5))

        # 绘制游戏结束画面
        elif life_num == 0:
            # 背景音乐停止
            pygame.mixer.music.stop()

            # 停止全部音效
            pygame.mixer.stop()

            # 绘制结束画面
            gameover_text = gameover_font.render("Score: " + str(score), True, (255, 255, 255))
            gameover_text_rect = gameover_text.get_rect()
            gameover_text_rect.left, gameover_text_rect.top = \
                (width - gameover_text_rect.width) // 2, height // 3
            screen.blit(gameover_text, gameover_text_rect)

            again_rect.left, again_rect.top = \
                (width - again_rect.width) // 2, \
                gameover_text_rect.bottom + 50
            screen.blit(again_image, again_rect)

            gameover_rect.left, gameover_rect.top = \
                (width - again_rect.width) // 2, \
                again_rect.bottom + 10
            screen.blit(gameover_image, gameover_rect)

            # 检测用户的鼠标操作
            # 如果用户按下鼠标左键
            if pygame.mouse.get_pressed()[0]:
                # 获取鼠标坐标
                pos = pygame.mouse.get_pos()
                # 如果用户点击“重新开始”
                if again_rect.left < pos[0] < again_rect.right and \
                        again_rect.top < pos[1] < again_rect.bottom:
                    # 调用main函数，重新开始游戏
                    main()
                # 如果用户点击“结束游戏”
                elif gameover_rect.left < pos[0] < gameover_rect.right and \
                        gameover_rect.top < pos[1] < gameover_rect.bottom:
                    # 退出游戏
                    pygame.quit()
                    sys.exit()

                    # 绘制暂停按钮
        screen.blit(paused_image, paused_rect)

        # 切换图片
        if not (delay % 5):
            switch_image = not switch_image

        delay -= 1
        if not delay:
            delay = 100

        pygame.display.flip()
        clock.tick(60)


if __name__ == "__main__":
    try:
        main()
    except SystemExit:
        pass
    except:
        traceback.print_exc()
        pygame.quit()
        input()
